class Race
  attr_reader :name;
  
  def initialize(name)
    @name = name;
  end

end

class World
  attr_reader :name, :races;
  
  def initialize(name, &block)
    @name = name;
    @races = {};
    instance_eval(&block) if block_given?;
  end
  
  protected
  def race(name)
    erace = Race.new(name);
    @races[erace.name] = erace;
  end
  
end

class Game
  attr_reader :name, :worlds;
  
  def initialize(name, &block)
    @name = name;
    @worlds = {};
    instance_eval(&block);
  end
  
  def play(&block)
    PlayGame.new(self, &block);
  end
  
  protected
  def world(name, &block)
    eworld = World.new(name, &block);
    @worlds[eworld.name] = eworld;
  end
  
end

class Person
  attr_reader :name, :world, :race;
  
  def initialize(opts)
    @name = opts[:name];
    @world = opts[:world];
    @race = opts[:race]
  end
  
  def like?(person)
    person.race == @race && person.world == @world;
  end
  
end

class PlayGame
  
  def initialize(game, &block)
    @game = game;
    @player = nil;
    instance_eval(&block);
  end
  
  protected
  alias_method :method_missing2, :method_missing;
  
  def method_missing(method, *args, &block)
    if args[0].kind_of?(Hash) && args[0][:is]
      somebody(method, args[0]);
    else
      method_missing2(method, *args, &block);
    end
  end
  
  def somebody(nick, opts)
    world = @game.worlds[opts[:from]];
    race = world.races[opts[:of_race]];
    person = Person.new(:name => opts[:is], :world => world, :race => race);
    (class << self; self; end).class_eval do
      define_method(nick){person;};
    end
  end
  
  def i(opts)
    somebody(:i, opts.merge(:is => opts[:am]));
  end
    
end

